// @Author EthanScriptOn
// @Desc
package pool

import (
	"gitee.com/fatzeng/srf_switch_basic_components/proxy/interceptor"
	"gitee.com/fatzeng/srf_switch_basic_components/queue"
	"time"
)

// DefaultWorker default worker
type DefaultWorker struct {
	*queue.QueueLoadMonitor                                 // QueueLoadMonitor Monitor for the queue
	weight                  int                             // weight weight
	workerQueue             queue.Queue                     // workerQueue WorkQueues
	destroy                 bool                            // destroy Whether it has been destroyed
	before                  *interceptor.InterceptorOptions // before Pre-submission actions
	after                   *interceptor.InterceptorOptions // after Post-actions for submissions
}

func GenerateDefaultWorker(workerQueue queue.Queue, weight int) *DefaultWorker {
	return &DefaultWorker{
		QueueLoadMonitor: queue.GenerateQueueLoadMonitor(workerQueue),
		weight:           weight,
		workerQueue:      workerQueue,
	}
}

// SetSubmitBeforeOption The pre-commit action wraps the action into an interceptor
func (d *DefaultWorker) SetSubmitBeforeOption(option func(task Task) error) (err error) {
	options, err := interceptor.GenerateInterceptorOptions(func(task Task) error {
		return option(task)
	})
	if err != nil {
		return err
	}
	d.before = options
	return
}

// SetSubmitAfterOption Commit a post-action, wrapping the action as an interceptor
func (d *DefaultWorker) SetSubmitAfterOption(option func(task Task) error) (err error) {
	options, err := interceptor.GenerateInterceptorOptions(func(task Task) error {
		return option(task)
	})
	if err != nil {
		return err
	}
	d.after = options
	return
}

// GetWeight Get weights
func (d *DefaultWorker) GetWeight() int {
	return d.weight
}

// GetLoadFactor Get the load situation
func (d *DefaultWorker) GetLoadFactor() float64 {
	return d.QueueLoadMonitor.GetLoadPercentage()
}

// GetQueue Get the queue
func (d *DefaultWorker) GetQueue() queue.Queue {
	return d.workerQueue
}

// Submit Task submission
func (d *DefaultWorker) Submit(task Task) {
	if d.destroy {
		return
	}
	if d.before != nil {
		d.before.SetParams([]interface{}{task})
		d.before.Call()
		if err := d.before.GetError(); err != nil {
			d.before.OnError(err)
			return
		}
	}
	d.workerQueue.Push(task)
	if d.after != nil {
		d.after.Call()
		if err := d.after.GetError(); err != nil {
			d.after.OnError(err)
			return
		}
	}
}

// Destroy Destroy a worker
func (d *DefaultWorker) Destroy() {
	d.destroy = true
	go func() {
		for {
			if d.workerQueue.QueueLen() == 0 {
				if !d.workerQueue.IsClose() {
					d.workerQueue.Close()
					return
				}
			}
			select {
			case <-time.After(1 * time.Microsecond):
			}
		}
	}()
}

// Initialization Initialization of the worker
func (d *DefaultWorker) Initialization() error {
	return nil
}
